using System;
using System.Security.Principal;
using System.Web.Mvc;
using MvcContrib.Pagination;
using MvcContrib.Sorting;
using MvcContrib.UI.Grid;
using Webbness.Mvc.Models;
using Webbness.Mvc.SubSonic;

namespace Webbness.Mvc.Controllers
{
    [Authorize(Roles = "admin")]
    public class SecureUserController<TUser, TJoin, TRole> : Controller
        where TUser : SecurityUser<TUser, TJoin, TRole>, new()
        where TRole : SecurityRole<TRole, TJoin, TUser>, new()
        where TJoin : SecurityUserInRole<TRole, TJoin, TUser>, new()
    {
        protected const int pageSize = 10;

        public virtual IPrincipal CurrentUser
        {
            get { return User; }
        }

        public virtual ActionResult Delete(int id)
        {
            var mod = Repository.Repo.Single<TUser>(id);
            return View("Scaffold", mod);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult Delete(int id, string confirmButton)
        {
            Repository.Repo.Delete<TUser>(id);
            ModelState.Clear();
            ViewData["results"] = "Deleted Successfully";
            return View("Scaffold");
        }

        public virtual ActionResult Edit(object id)
        {
            var mod = Repository.Repo.Single<TUser>(id);
            return View("Scaffold", mod);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult Edit(TUser mod)
        {
            if (checkDate(mod.CreationDate))
                mod.CreationDate = DateTime.Now;
            if (checkDate(mod.LastActivityDate))
                mod.LastActivityDate = DateTime.Now;
            if (checkDate(mod.LastLockedOutDate))
                mod.LastLockedOutDate = DateTime.Now;
            if (checkDate(mod.LastLoginDate))
                mod.LastLoginDate = DateTime.Now;
            if (checkDate(mod.LastPasswordChangedDate))
                mod.LastPasswordChangedDate = DateTime.Now;

            if (ModelState.IsValid)
            {
                Repository.Repo.Update(mod);
                ModelState.Clear();
                RouteData.Values["action"] = "Display";
                ViewData["results"] = "Saved Successfully";
            }
            return View("Scaffold", mod);
        }

        private static bool checkDate(DateTime date)
        {
            var x = date > new DateTime(1757, 1, 1);
            var y = date < new DateTime(9999, 12, 31);

            return date < new DateTime(1757, 1, 1) || date > new DateTime(9999, 12, 31);
        }

        public virtual ActionResult Display(object id)
        {
            var mod = Repository.Repo.Single<TUser>(id);
            return View("Scaffold", mod);
        }

        public virtual ActionResult Add()
        {
            var mod = new TUser();
            return View("Scaffold", mod);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult Add(TUser mod)
        {
            mod.CreationDate = DateTime.Now;
            mod.LastActivityDate = DateTime.Now;
            mod.LastLockedOutDate = DateTime.Now;
            mod.LastLoginDate = DateTime.Now;
            mod.LastPasswordChangedDate = DateTime.Now;

            if (ModelState.IsValid)
            {
                object i = Repository.Repo.Add(mod);
                ViewData["results"] = "Saved Successfully";
                RouteData.Values["action"] = "Display";
                RouteData.Values["id"] = i.ToString();
                ModelState.Clear();
            }
            return View("Scaffold", mod);
        }

        public virtual ActionResult Error()
        {
            return View("Error");
        }

        public virtual ActionResult Index(int? page, GridSortOptions sort)
        {
            ViewData["sort"] = sort;
            var queryable = Repository.Repo.All<TUser>();

            queryable = string.IsNullOrEmpty(sort.Column) ? queryable.OrderBy("Id", SortDirection.Ascending) : queryable.OrderBy(sort.Column, sort.Direction);

            var pagination = queryable.AsPagination(page ?? 1, pageSize);

            return View("Scaffold", pagination);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        [Authorize(Roles = "admin")]
        public virtual ActionResult UpdateRole(int user, int role, bool add)
        {
            if (user == 0 || role == 0)
            {
                return Content("Unexpected values. No Update.");
            }
            var i = Repository.Repo.Single<TJoin>(uir => uir.RoleID == role && uir.UserID == user);
            string output = "No action taken.";
            if (add && (i == null))
            {
                var ur = new TJoin { UserID = user, RoleID = role };
                Repository.Repo.Add(ur);
                output = "Role added to user";
            }
            else if (i != null)
            {
                output = "Role removed from user.";
                Repository.Repo.Delete<TJoin>(i.Id);
            }
            return Content(output);
        }
    }
}